package com.MedDroid.control;

import com.MedDroid.MainApp;
import com.MedDroid.control.message.Message;
import com.MedDroid.entities.Database;
import com.MedDroid.entities.Permissions;
import com.MedDroid.entities.User;
import com.MedDroid.entities.database.DatabaseRow;
import com.MedDroid.entities.schedule.ScheduleEvent;

import java.util.ArrayList;

/**
 * Created with IntelliJ IDEA.
 * User: Romen
 * Date: 19/11/13
 * Time: 9:40 PM
 * Description: Main control class for the database.
 */
public class DatabaseControl extends AbstractControl
{
	//TODO UNIQUE IDS
	//TODO IMPORT EXPORT

	//PRIVATE VARIABLES
	Database UserData;
	final String UserDataFileName = "UserData.txt";
	boolean UserDataExportFlag = false;
	Database ScheduleData;
	final String ScheduleDataFileName = "ScheduleData.txt";
	final String ControllerConfigFileName = "DatabaseConfig.dat";
	boolean ScheduleDataExportFlag = false;
	boolean doExport = false;
	boolean Android;
	int NextUserID;
	int NextEventID;

	//CONSTRUCTOR
	public DatabaseControl(MainApp A)
	{
		super(A);

		UserData = new Database();
		ScheduleData = new Database();

		Android = true;

		nextUserID();
		nextEventID();
	}

	//OVERRIDE METHODS
	@Override
	public Message processMessage(Message Msg)
	{
		//On error
		return new Message(this,0,"NULL");
	}

	//LIFECYCLE METHODS
	public void startup()
	{
		//Load data from files
		UserData.importData(ApplicationContext,UserDataFileName);
		ScheduleData.importData(ApplicationContext,ScheduleDataFileName);

		//Decrypt data
		UserData.decrypt();
		ScheduleData.decrypt();

		UserData.clearDatabase();

		//Add super user
		addSuperUser();

		//Add Test user
		addUser(new User());
	}

	public void export()
	{
		//Encrypt data
		UserData.encrypt();
		ScheduleData.encrypt();

		//Write data to files
		UserData.exportData(ApplicationContext, UserDataFileName);
		ScheduleData.exportData(ApplicationContext, ScheduleDataFileName);
	}

	public void shutdown()
	{
		export();
	}

	//USER METHODS
	private void nextUserID()
	{
		int id = 1;
		while(UserData.findRow(User.UserIDStr,Integer.toString(id)) != null)
		{
			id++;
		}
		NextUserID = id;
	}

	public void addUser(User NewUser)
	{
		if (UserData.findRow(User.UserIDStr,Integer.toString(NextUserID))!=null)
		{
			MainApp.log("DOUBLE USER ID FOUND");
		}
		NewUser.setUserID(NextUserID);
		NewUser.addUserAccess(NewUser.getUserID());
		UserData.addRow(NewUser.buildRow());
		nextUserID();
		addAllUsersAccess(0);
		for (DatabaseRow  Row : UserData.getDatabase())
		{
			User New = User.buildfromRow(Row);
			if (New.getAccess().getUserType() == Permissions.UAdmin);
			{
				addAllUsersAccess(New.getUserID());
			}
		}
		UserDataExportFlag = true;
	}

	public void addSuperUser()
	{
		User NewUser = new User();
		NewUser.setSuper();
		NewUser.addUserAccess(0);
		updateUser(0, NewUser);
		UserDataExportFlag = true;
	}

	public void addAllUsersAccess(int UserID)
	{
		User Update = findUser(User.UserIDStr,Integer.toString(UserID));
		for (DatabaseRow Row : UserData.getDatabase())
		{
			Update.addUserAccess(Integer.parseInt(Row.getValue(User.UserIDStr)));
		}
		UserData.replaceRow(User.UserIDStr,Integer.toString(UserID),Update.buildRow());
	}

	public void updateUser(int UserID, User UpdatedUser)
	{
		UserData.replaceRow(User.UserIDStr,Integer.toString(UserID), UpdatedUser.buildRow());
	}

	public void removeUser(int UserID)
	{
		DatabaseRow UserRow = UserData.findRow("UserID", Integer.toString(UserID));
		if (UserRow != null)
		{
			UserData.removeRow(UserRow);
		}
		//Remove user from all User Accesses
		for (DatabaseRow Row : UserData.getDatabase())
		{
			User CurrentRow = User.buildfromRow(Row);
			CurrentRow.removeUserAccess(UserID);
			UserData.replaceRow(Row,CurrentRow.buildRow());
		}
		UserDataExportFlag = true;
	}

	public User getUser(int UserID)
	{
		DatabaseRow UserRow = UserData.findRow("UserID",Integer.toString(UserID));
		return User.buildfromRow(UserRow);
	}

	public User findUser(String FieldName, String Value)
	{
		DatabaseRow Row = UserData.findRow(FieldName, Value);
		if (Row != null)
		{
			MainApp.log("Entry Found.");
			return User.buildfromRow(Row);
		}
		MainApp.log("Entry with " + FieldName + " and value of " + Value + " does not exist.");
		return null;
	}

	//SCHEDULE METHODS
	private void nextEventID()
	{
		int id = 1;
		while(ScheduleData.findRow("EventID",Integer.toString(id)) != null)
		{
			id++;
		}
		NextEventID = id;
	}

	public void addEvent(ScheduleEvent Event, int UserId)
	{
		Event.setEventID(NextEventID);
		Event.addMember(UserId);
		ScheduleData.addRow(Event.buildRow());
		NextEventID++;
		ScheduleDataExportFlag = true;
	}

	public void removeEvent(int EventID)
	{
		DatabaseRow EventRow = ScheduleData.findRow("EventID", Integer.toString(EventID));
		if (EventRow != null)
		{
			ScheduleData.removeRow(EventRow);
		}
		ScheduleDataExportFlag = true;
	}

	public ScheduleEvent getEvent(int EventID)
	{
		DatabaseRow EventRow = ScheduleData.findRow("EventID",Integer.toString(EventID));
		return ScheduleEvent.buildfromRow(EventRow);
	}

	public ArrayList<Integer> getEvents(int UserID)
	{
		ArrayList<Integer> list = new ArrayList<Integer>();
		for (DatabaseRow Row : ScheduleData.getDatabase())
		{
			ScheduleEvent Event = ScheduleEvent.buildfromRow(Row);
			if (Event.hasMember(UserID))
			{
				list.add(Event.getEventID());
			}
		}
		return list;
	}
}
